package com.nf;

import javax.sql.DataSource;
import java.sql.*;
import java.util.Arrays;

/**
 * 　　* @description: TODO
 * 　　* @param
 * 　　* @return
 * 　　* @throws
 * 　　* @author Administrator
 * 　　* @date $ $
 */
public abstract class MiniAbstractQueryRunner {

    private volatile boolean pmdKnownBroken = false;

    protected final DataSource ds;

    public MiniAbstractQueryRunner() {
        this(null,false);
    }

    public MiniAbstractQueryRunner(boolean pmdKnownBroken) {
        this(null,pmdKnownBroken);
    }

    public MiniAbstractQueryRunner(DataSource ds) {
        this(ds,false);
    }

    public MiniAbstractQueryRunner(DataSource ds, boolean pmdKnownBroken) {
        this.pmdKnownBroken = pmdKnownBroken;
        this.ds = ds;
    }

    protected void close(Statement stmt) throws SQLException {
        MiniDbUtils.close(stmt);
    }

    protected void close(ResultSet resultSet) throws SQLException {
        MiniDbUtils.close(resultSet);
    }

    protected void close(Connection conn) throws SQLException {
        MiniDbUtils.close(conn);
    }

    public DataSource getDataSource() {
        return this.ds;
    }

    protected Connection prepareConnection() throws SQLException {
        if (this.getDataSource() == null) {
            throw new SQLException(
                    "QueryRunner requires a DataSource to be "
                            + "invoked in this way, or a Connection should be passed in");
        }
        return this.getDataSource().getConnection();
    }

    protected void rethrow(SQLException cause, String sql, Object... params)
            throws SQLException {
        String causeMessage = cause.getMessage();
        if (causeMessage == null) {
            causeMessage = "";
        }
        StringBuffer msg = new StringBuffer(causeMessage);
        msg.append(" Query: ");
        msg.append(sql);
        msg.append(" Parameters: ");
        if (params == null) {
            msg.append("[]");
        } else {
            msg.append(Arrays.deepToString(params));
        }
        SQLException e = new SQLException(msg.toString(), cause.getSQLState(),
                cause.getErrorCode());
        e.setNextException(cause);
        throw e;
    }

    protected PreparedStatement prepareStatement(Connection connection, String sql)
            throws SQLException {
        PreparedStatement ps = connection.prepareStatement(sql);
        return ps;
    }

    public void fillStatement(PreparedStatement stmt, Object... params) throws SQLException {
        ParameterMetaData pmd = null;
        if (!pmdKnownBroken) {
            try {
                pmd = stmt.getParameterMetaData();
                if (pmd == null) {
                    pmdKnownBroken = true;
                } else {
                    int stmtCount = pmd.getParameterCount();
                    int paramsCount = params == null ? 0 : params.length;
                    if (stmtCount != paramsCount) {
                        throw new SQLException("Wrong number of parameters: expected "
                                + stmtCount + ", was given " + paramsCount);
                    }
                }
            } catch (SQLFeatureNotSupportedException ex) {
                pmdKnownBroken = true;
            }
        }

        if (params == null) {
            return;
        }

        for (int i = 0; i < params.length; i++) {
            if (params[i] != null) {
                stmt.setObject(i + 1, params[i]);
            } else {
                int sqlType = Types.VARCHAR;
                if (!pmdKnownBroken) {
                    try {
                        sqlType = pmd.getParameterType(i + 1);
                    } catch (SQLException e) {
                        pmdKnownBroken = true;
                    }
                }
                stmt.setNull(i + 1, sqlType);
            }
        }
    }
}
